import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:website/app/application/bloc.dart';
import 'package:website/injection_container.dart' as di;
import 'package:website/splash_screen/presentation/page/page.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/bloc.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_configs/account_page_config.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_configs/app_navigator_page_config.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_configs/documentation_page_config.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_configs/faq_page_config.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_configs/home_page_config.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_configs/signing_in_page_config.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_configs/signing_up_page_config.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_configs/web_purchase_item_page_config.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_models/account_page_model.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_models/app_navigator_page_model.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_models/documentation_page_model.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_models/faq_page_model.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_models/home_page_model.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_models/signing_in_page_model.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_models/signing_up_page_model.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_models/splash_screen_model.dart';
import 'package:website.core/core/application/blocs/app_navigator_bloc/models/page_models/web_purchase_item_page_model.dart';
import 'package:website.core/core/presentation/widgets/app_navigator_page.dart';
import 'package:website.core/injection_container.dart' as core_di;
import 'package:website.home/documentation_page/presentation/page/page.dart';
import 'package:website.home/faq_page/presentation/page/page.dart';
import 'package:website.home/home_page/presentation/page/page.dart';
import 'package:website.home/signing_in_page/presentation/page/page.dart';
import 'package:website.home/signing_up_page/presentation/page/page.dart';
import 'package:website.home/web_purchase_item_page/presentation/page/page.dart';
import 'package:website.home.account/account_page/presentation/page/page.dart';

final _navigatorKey = GlobalKey<NavigatorState>();

class AppRouterDelegate extends RouterDelegate<AppNavigatorPageConfig>
    with ChangeNotifier, PopNavigatorRouterDelegateMixin {
  AppRouterDelegate();

  @override
  GlobalKey<NavigatorState> get navigatorKey => _navigatorKey;

  AppBloc get _appBloc {
    return di.sl<AppBloc>();
  }

  AppNavigatorBloc get _navigatorBloc {
    return core_di.sl<AppNavigatorBloc>();
  }

  AppNavigatorPage _mapPageModelToNavigatorPage(AppNavigatorPageModel pageModel) {
    late Widget page;

    if (pageModel is SplashScreenModel) {
      page = SplashScreen(
        key: ValueKey(pageModel.pageId),
        pageModel: pageModel,
      );
    } else if (pageModel is HomePageModel) {
      page = HomePage(
        key: ValueKey(pageModel.pageId),
        pageModel: pageModel,
      );
    } else if (pageModel is FaqPageModel) {
      page = FaqPage(
        key: ValueKey(pageModel.pageId),
        pageModel: pageModel,
      );
    } else if (pageModel is SigningUpPageModel) {
      page = SigningUpPage(
        key: ValueKey(pageModel.pageId),
        pageModel: pageModel,
      );
    } else if (pageModel is SigningInPageModel) {
      page = SigningInPage(
        key: ValueKey(pageModel.pageId),
        pageModel: pageModel,
      );
    } else if (pageModel is WebPurchaseItemPageModel) {
      page = WebPurchaseItemPage(
        key: ValueKey(pageModel.pageId),
        pageModel: pageModel,
      );
    } else if (pageModel is AccountPageModel) {
      page = AccountPage(
        key: ValueKey(pageModel.pageId),
        pageModel: pageModel,
      );
    } else if (pageModel is DocumentationPageModel) {
      page = DocumentationPage(
        key: ValueKey(pageModel.pageId),
        pageModel: pageModel,
      );
    }

    return AppNavigatorPage(
      pageModel: pageModel,
      child: page,
    );
  }

  @override
  Widget build(BuildContext context) {
    return BlocConsumer<AppNavigatorBloc, AppNavigatorBlocState>(
      bloc: _navigatorBloc,
      listener: (context, state) {
        notifyListeners();
      },
      builder: (context, state) {
        final pages = state.pageModels.map(_mapPageModelToNavigatorPage).toList();

        return Navigator(
          key: navigatorKey,
          pages: pages,
          onPopPage: (route, result) {
            _navigatorBloc.handlePop();
            return false;
          },
        );
      },
    );
  }

  @override
  Future<void> setNewRoutePath(AppNavigatorPageConfig pageConfig) async {
    late final AppNavigatorPageModel pageModel;

    if (pageConfig is HomePageConfig) {
      pageModel = HomePageModel();
    } else if (pageConfig is FaqPageConfig) {
      pageModel = FaqPageModel();
    } else if (pageConfig is DocumentationPageConfig) {
      pageModel = DocumentationPageModel();
    } else if (pageConfig is SigningUpPageConfig) {
      pageModel = SigningUpPageModel(
        targetPageModel: HomePageModel(),
      );
    } else if (pageConfig is SigningInPageConfig) {
      pageModel = SigningInPageModel(
        targetPageModel: HomePageModel(),
      );
    } else if (pageConfig is WebPurchaseItemPageConfig) {
      pageModel = WebPurchaseItemPageModel();
    } else if (pageConfig is AccountPageConfig) {
      late final AccountPageFragmentModel fragmentModel;

      final fragmentConfig = pageConfig.fragmentConfig;

      if (fragmentConfig is AccountOverviewAccountPageFragmentConfig) {
        fragmentModel = const AccountOverviewAccountPageFragmentModel();
      }

      if (fragmentConfig is PurchaseManagementAccountPageFragmentConfig) {
        fragmentModel = const PurchaseManagementAccountPageFragmentModel();
      }

      if (fragmentConfig is TransactionHistoryAccountPageFragmentConfig) {
        fragmentModel = const TransactionHistoryAccountPageFragmentModel();
      }

      if (fragmentConfig is PaymentMethodAccountPageFragmentConfig) {
        fragmentModel = const PaymentMethodAccountPageFragmentModel();
      }

      pageModel = AccountPageModel(
        fragmentModel: fragmentModel,
      );
    }

    _appBloc.setNewPage(
      pageModel: pageModel,
    );

    return SynchronousFuture(null);
  }

  @override
  AppNavigatorPageConfig? get currentConfiguration {
    final pageModel = _navigatorBloc.state.pageModels.last;

    if (pageModel is SplashScreenModel) {
      return null;
    }

    if (pageModel is HomePageModel) {
      return const HomePageConfig();
    }

    if (pageModel is FaqPageModel) {
      return const FaqPageConfig();
    }

    if (pageModel is DocumentationPageModel) {
      return const DocumentationPageConfig();
    }

    if (pageModel is SigningUpPageModel) {
      return const SigningUpPageConfig();
    }

    if (pageModel is SigningInPageModel) {
      return const SigningInPageConfig();
    }

    if (pageModel is WebPurchaseItemPageModel) {
      return const WebPurchaseItemPageConfig();
    }

    if (pageModel is AccountPageModel) {
      final fragmentModel = pageModel.fragmentModel;

      late final AccountPageFragmentConfig fragmentConfig;

      if (fragmentModel is AccountOverviewAccountPageFragmentModel) {
        fragmentConfig = const AccountOverviewAccountPageFragmentConfig();
      }

      if (fragmentModel is PurchaseManagementAccountPageFragmentModel) {
        fragmentConfig = const PurchaseManagementAccountPageFragmentConfig();
      }

      if (fragmentModel is TransactionHistoryAccountPageFragmentModel) {
        fragmentConfig = const TransactionHistoryAccountPageFragmentConfig();
      }

      if (fragmentModel is PaymentMethodAccountPageFragmentModel) {
        fragmentConfig = const PaymentMethodAccountPageFragmentConfig();
      }

      return AccountPageConfig(
        fragmentConfig: fragmentConfig,
      );
    }

    throw UnimplementedError();
  }
}
